package com.sprucetec.live.aspect;

import com.alibaba.fastjson.JSONObject;
import com.google.common.util.concurrent.RateLimiter;
import com.sprucetec.live.annotation.GuavaTateLimeter;
import com.sprucetec.live.common.util.RespCode;
import com.sprucetec.live.common.util.ResponseJsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName GuavaAspect
 * @Description:
 * @Author Kenny
 * @Date 2020/4/23
 **/
@Aspect
@Component
@Slf4j
public class GuavaAspect {
    @Autowired
    private HttpServletResponse response;

    //创建切点
    @Pointcut("@annotation(com.sprucetec.live.annotation.GuavaTateLimeter)")
    public void guaLog() {
    }

    private RateLimiter rateLimiter = RateLimiter.create(2);

    @Around("guaLog()")
    public Object limit(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        GuavaTateLimeter annotation = signature.getMethod().getDeclaredAnnotation(GuavaTateLimeter.class);
        if (annotation == null) {
            return proceedingJoinPoint.proceed();
        } else {
            rateLimiter.setRate(annotation.limit());
            if (rateLimiter.tryAcquire(annotation.timeOut(), TimeUnit.SECONDS)) {
                return proceedingJoinPoint.proceed();
            } else {
                fullback();
            }
        }
        return null;
    }

    public void fullback() {
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("rspCode", RespCode.REQUEST_LIMIT.getCode());
        data.put("rspMsg", "当前操作人数过多，请稍后操作！");
        data.put("body", null);
        data.put("success", false);
        ResponseJsonUtils.json(response, data);
    }

}
